<?php

namespace Nece\Sdk\Coze\Api;

use Nece\Sdk\Coze\ApiAbstract;
use Nece\Sdk\Coze\Entity\EnterMessageList;

/**
 * 对话
 *
 * @author gjw
 * @created 2025-04-23 14:02:06
 */
class Chat extends ApiAbstract
{
    /**
     * 发起对话
     *
     * @author gjw
     * @created 2025-04-23 14:07:52
     *
     * @param string $conversation_id 标识对话发生在哪一次会话中。
     * @param string $bot_id 要进行会话聊天的智能体ID。
     * @param string $user_id 标识当前与智能体对话的用户，由使用方自行定义、生成与维护。user_id 用于标识对话中的不同用户，不同的 user_id，其对话的上下文消息、数据库等对话记忆数据互相隔离。如果不需要用户数据隔离，可将此参数固定为一个任意字符串，例如 123，abc 等。
     * @param EnterMessageList $additional_messages 消息对象
     * @param boolean $stream 是否启用流式返回。
     * @param array $custom_variables 智能体提示词中定义的变量。在智能体 prompt 中设置变量 {{key}} 后，可以通过该参数传入变量值，同时支持 Jinja2 语法。kv对 
     * @param boolean $auto_save_history 是否保存本次对话记录。
     * @param array $meta_data 附加信息，通常用于封装一些业务相关的字段。查看对话详情时，扣子会透传此附加信息，查看消息列表时不会返回该附加信息。自定义键值对，应指定为 Map 对象格式。长度为 16 对键值对，其中键（key）的长度范围为 1～64 个字符，值（value）的长度范围为 1～512 个字符。kv对
     * @param array $extra_params 附加参数，通常用于特殊场景下指定一些必要参数供模型判断，例如指定经纬度，并询问智能体此位置的天气。该参数不会传给工作流。kv对
     * @param string $shortcut_command 快捷指令信息。你可以通过此参数指定此次对话执行的快捷指令，必须是智能体已绑定的快捷指令。
     * @param array $parameters 给自定义参数赋值并传给对话流。你可以根据实际业务需求，在对话流开始节点的输入参数中设置自定义参数，调用本接口发起对话时，可以通过parameters 参数传入自定义参数的值并传给对话流。具体示例代码请参见自定义用户变量kv对
     * @param boolean $enable_card 设置问答节点返回的内容是否为卡片形式。默认为 false。
     * @return array
     */
    public function chat(string $conversation_id, string $bot_id, string $user_id, ?EnterMessageList $additional_messages = null, bool $stream = false, array $custom_variables = [], bool $auto_save_history = true, array $meta_data = [], array $extra_params = [], string $shortcut_command = '', array $parameters = [], bool $enable_card = false)
    {
        $api = '/v3/chat';

        $query = array(
            'conversation_id' => $conversation_id,
        );

        $params = array(
            'bot_id' => $bot_id,
            'user_id' => $user_id,
            'enable_card' => $enable_card,
        );

        if (!empty($additional_messages)) {
            $params['additional_messages'] = $additional_messages->toArray();
        }

        $params['stream'] = $stream;

        if (!empty($custom_variables)) {
            $params['custom_variables'] = $custom_variables;
        }

        if ($auto_save_history) {
            $params['auto_save_history'] = $auto_save_history;
        }

        if (!empty($meta_data)) {
            $params['meta_data'] = $meta_data;
        }

        if (!empty($extra_params)) {
            $params['extra_params'] = $extra_params;
        }

        if (!empty($shortcut_command)) {
            $params['shortcut_command'] = array('command_id' => $shortcut_command);
        }

        if (!empty($parameters)) {
            $params['parameters'] = $parameters;
        }

        return $this->post($api, $params, $query);
    }

    /**
     * 查看对话详情
     *
     * @author gjw
     * @created 2025-04-23 14:08:51
     *
     * @param string $conversation_id 会话的唯一标识。
     * @param string $chat_id 对话的唯一标识。
     * @return array
     */
    public function retrieve(string $conversation_id, string $chat_id)
    {
        $api = '/v3/chat/retrieve';
        $query = array(
            'conversation_id' => $conversation_id,
            'chat_id' => $chat_id,
        );

        return $this->get($api, $query);
    }

    /**
     * 查看对话消息详情
     *
     * @author gjw
     * @created 2025-04-23 14:10:46
     *
     * @param string $conversation_id 会话的唯一标识。
     * @param string $chat_id 对话的唯一标识。
     * @return array
     */
    public function list(string $conversation_id, string $chat_id)
    {
        $api = '/v3/chat/message/list';
        $query = array(
            'conversation_id' => $conversation_id,
            'chat_id' => $chat_id,
        );

        return $this->get($api, $query);
    }

    /**
     * 提交工具执行结果
     *
     * @author gjw
     * @created 2025-04-23 14:13:03
     *
     * @param string $conversation_id 会话的唯一标识。
     * @param string $chat_id 对话的唯一标识。
     * @param array $tool_outputs 工具执行结果。 https://www.coze.cn/open/docs/developer_guides/chat_submit_tool_outputs
     * @param boolean $stream 是否开启流式响应。true：填充之前对话中的上下文，继续流式响应。false：（默认）非流式响应，仅回复对话的基本信息。
     * @return array
     */
    public function submitToolOutputs(string $conversation_id, string $chat_id, array $tool_outputs, bool $stream = false)
    {
        $api = '/v3/chat/submit_tool_outputs';

        $query = array(
            'conversation_id' => $conversation_id,
            'chat_id' => $chat_id,
        );

        $param = array(
            'tool_outputs' => $tool_outputs
        );

        if ($stream) {
            $params['stream'] = $stream;
        }
        return $this->post($api, $param, $query);
    }

    /**
     * 取消进行中的对话
     *
     * @author gjw
     * @created 2025-04-23 14:14:10
     *
     * @param string $conversation_id 会话 ID
     * @param string $chat_id 对话 ID
     * @return array
     */
    public function cancel(string $conversation_id, string $chat_id)
    {
        $api = '/v3/chat/cancel';
        $params = array(
            'conversation_id' => $conversation_id,
            'chat_id' => $chat_id,
        );

        return $this->post($api, $params);
    }
}
